#include <stdlib.h>
#include "Arbre.h"
#include "Symbole.h"
#include "SymboleValue.h"
#include "sstream"

////////////////////////////////////////////////////////////////////////////////
// NoeudSeqInst
////////////////////////////////////////////////////////////////////////////////

string itos(int i) {
	string s;
	stringstream out;
	out << i;
	return out.str();
}

string ftos(float f) {
	string s;
	stringstream out;
	out << f;
	return out.str();
}

NoeudSeqInst::NoeudSeqInst() : tabInst() {
}

////////////////////////////////////////////////////////////////////////////////
Multype* NoeudSeqInst::getValeur() {
  Multype* valeur = NULL;
  for (unsigned int i=0; i<tabInst.size(); i++)
    {
        valeur = tabInst[i]->getValeur();  // on evalue chaque instruction de la séquence
    }
  return valeur; // par convention, resultat = valeur de la derniere instruction
}

////////////////////////////////////////////////////////////////////////////////
void NoeudSeqInst::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Sequence de " << tabInst.size() << " instruction(s)" << endl;
  for (unsigned int i=0; i<tabInst.size(); i++)
    tabInst[i]->afficher(indentation+1); // on affiche les fils en augmentant l'indentation
}

////////////////////////////////////////////////////////////////////////////////
void NoeudSeqInst::ajouteInstruction(Noeud* instruction) {
  tabInst.push_back(instruction);
}

//////////////////////////////////////////////////////////////////////////////
string NoeudSeqInst::getCode(int indent) {


	string buffer = "";
	for (unsigned int i=0; i<tabInst.size(); i++) {
		for (int j = 0 ; j < indent ; j ++)
			buffer = buffer + "\t";
		buffer = buffer + tabInst[i]->getCode(indent) + "\n";
	}
	return buffer;
}

////////////////////////////////////////////////////////////////////////////////
// NoeudAffectation
////////////////////////////////////////////////////////////////////////////////

NoeudAffectation::NoeudAffectation(Noeud* variable, Noeud* expression) {
  this->variable=variable;
  this->expression=expression;
}

////////////////////////////////////////////////////////////////////////////////
Multype* NoeudAffectation::getValeur() {
  Multype* valeur = expression->getValeur(); // on évalue l'expression
  //((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
  if(typeid(*valeur) == typeid(TypeInt))
	{
		TypeInt* val = dynamic_cast<TypeInt*> (valeur);
		((SymboleValue*)variable)->setValeur(val->getValeur());
	}
  else if(typeid(*valeur) == typeid(TypeString))
	{
		TypeString* val = dynamic_cast<TypeString*> (valeur);
		((SymboleValue*)variable)->setValeur(val->getValeur());
	}
	else if(typeid(*valeur) == typeid(TypeFloat))
	{
		TypeFloat* val = dynamic_cast<TypeFloat*> (valeur);
		((SymboleValue*)variable)->setValeur(val->getValeur());
	}
	else if(typeid(*valeur) == typeid(TypeBool))
	{
		TypeBool* val = dynamic_cast<TypeBool*> (valeur);
		((SymboleValue*)variable)->setValeur(val->getValeur());
	}
  return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
string NoeudAffectation::getCode(int indent) {

	Multype* valeur = expression->getValeur();
	string affectation;
	SymboleValue* var = dynamic_cast<SymboleValue*> (variable);

	if(typeid(*valeur) == typeid(TypeInt)) {
		if ( typeid(*expression) == typeid(SymboleValue) ) {
			SymboleValue* temp = dynamic_cast<SymboleValue*>(expression);
			affectation = "int " + var->getChaine() + " = " + temp->getChaine() + ";";
		} else {
			affectation = "int " + var->getChaine() + " = " + expression->getCode(indent) + ";";
		}
	} else if(typeid(*valeur) == typeid(TypeFloat)) {
		if ( typeid(*expression) == typeid(SymboleValue) ) {
			SymboleValue* temp = dynamic_cast<SymboleValue*>(expression);
			affectation = "float " + var->getChaine() + " = " + temp->getChaine() + ";";
		} else {
			affectation = "float " + var->getChaine() + " = " + expression->getCode(indent) + ";";
		}
	} else if(typeid(*valeur) == typeid(TypeString)) {
		if ( typeid(*expression) == typeid(SymboleValue) ) {
			SymboleValue* temp = dynamic_cast<SymboleValue*>(expression);
			affectation = "string " + var->getChaine() + " = " + temp->getChaine() + ";";
		} else {
			affectation = "string " + var->getChaine() + " = " + expression->getCode(indent) + ";";
		}
	}

	return affectation;
}
////////////////////////////////////////////////////////////////////////////////
void NoeudAffectation::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Affectation" << endl;
  variable->afficher(indentation+1);   // on affiche variable et expression
  expression->afficher(indentation+1); // en augmentant l'indentation
}

////////////////////////////////////////////////////////////////////////////////
// NoeudOperateurBinaire
////////////////////////////////////////////////////////////////////////////////

NoeudOperateurBinaire::NoeudOperateurBinaire ( Symbole operateur,
                                               Noeud* operandeGauche,
                                               Noeud* operandeDroit) {
  this->operateur=operateur;
  this->operandeGauche=operandeGauche;
  this->operandeDroit=operandeDroit;
}

////////////////////////////////////////////////////////////////////////////////
Multype* NoeudOperateurBinaire::getValeur() {
  //Multype* valeur(0);
  Multype* og=operandeGauche->getValeur();
  Multype* od=operandeDroit->getValeur();
  if      (this->operateur=="+") //valeur = og+od;
  {
  		if( typeid(*og) == typeid(TypeString) and typeid(*od) == typeid(TypeString) )
  		{
  			TypeString* ogs = dynamic_cast<TypeString*> (og);
  			TypeString* ods = dynamic_cast<TypeString*> (od);
  			TypeString* valeur = new TypeString(ogs->getValeur() + ods->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  		{
  			TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  			TypeInt* odi = dynamic_cast<TypeInt*> (od);
  			TypeInt* valeur = new TypeInt(ogi->getValeur() + odi->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  		{
  			TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  			TypeFloat* odi = dynamic_cast<TypeFloat*> (od);
  			TypeFloat* valeur = new TypeFloat(ogi->getValeur() + odi->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeBool) and typeid(*od) == typeid(TypeBool) )
  		{
  			TypeBool* ogi = dynamic_cast<TypeBool*> (og);
  			TypeBool* odi = dynamic_cast<TypeBool*> (od);
  			TypeBool* valeur = new TypeBool(ogi->getValeur() or odi->getValeur());
  			return valeur;
  		}
  		else
  		{
  			cout << "Erreur pendant l'interpretation : ajout de 2 types différents" << endl;
	  		exit(0); // plus tard on levera une exception
  		}
  }
  else if (this->operateur=="-")//valeur = og-od;
  {
  	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  		{
  			TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  			TypeInt* odi = dynamic_cast<TypeInt*> (od);
  			TypeInt* valeur = new TypeInt(ogi->getValeur() - odi->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  		{
  			TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  			TypeFloat* odi = dynamic_cast<TypeFloat*> (od);
  			TypeFloat* valeur = new TypeFloat(ogi->getValeur() - odi->getValeur());
  			return valeur;
  		}
  		else
  		{
  			cout << "Erreur pendant l'interpretation : soustraction avec un autre type qu'Entier" << endl;
	  		exit(0); // plus tard on levera une exception
  		}
  	}
  else if (this->operateur=="*") //valeur = og*od;
  {
  	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  		{
  			TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  			TypeInt* odi = dynamic_cast<TypeInt*> (od);
  			TypeInt* valeur = new TypeInt(odi->getValeur() * ogi->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  		{
  			TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  			TypeFloat* odi = dynamic_cast<TypeFloat*> (od);
  			TypeFloat* valeur = new TypeFloat(ogi->getValeur() * odi->getValeur());
  			return valeur;
  		}
  		else if( typeid(*og) == typeid(TypeBool) and typeid(*od) == typeid(TypeBool) )
  		{
  			TypeBool* ogi = dynamic_cast<TypeBool*> (og);
  			TypeBool* odi = dynamic_cast<TypeBool*> (od);
  			TypeBool* valeur = new TypeBool(ogi->getValeur() and odi->getValeur());
  			return valeur;
  		}
  		else
  		{
  			cout << "Erreur pendant l'interpretation : multiplication avec un autre type qu'Entier" << endl;
	  		exit(0); // plus tard on levera une exception
  		}
  }
  else if (this->operateur=="/")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (odi->getValeur()!=0)
		{
			TypeInt* valeur = new TypeInt(ogi->getValeur() * odi->getValeur());
			return valeur;
		}
  		else
  		{
	  		cout << "Erreur pendant l'interpretation : division par zero" << endl;
	  		exit(0); // plus tard on levera une exception
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
        {
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (odi->getValeur()!=0.0)
		{
			TypeFloat* valeur = new TypeFloat(ogi->getValeur() * odi->getValeur());
			return valeur;
		}
  		else
  		{
	  		cout << "Erreur pendant l'interpretation : division par zero" << endl;
	  		exit(0); // plus tard on levera une exception
	  	}
	  }
	  else
	  {
	  	cout << "Erreur pendant l'interpretation : division avec des Type différents de Entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }
  else if (this->operateur=="<")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()< odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);

			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  	{
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()< odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
		else
		{
		    TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
  	}
	 else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }
  else if (this->operateur==">")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()> odi->getValeur())
		{
			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  	{
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()> odi->getValeur())
		{

			TypeInt* valeur = new TypeInt(1);

			return valeur;
		}
		else
		{
		    TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
  	}
	 else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }
  else if (this->operateur==">=")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()>= odi->getValeur())
		{
			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  	{
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()>= odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
		else
		{
		    TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
  	}
	 else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }
  else if (this->operateur=="<=")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()<= odi->getValeur())
		{
			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  	{
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()<= odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
		else
		{
            TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
  	}
	 else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }
  else if (this->operateur=="!=")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()!= odi->getValeur())
		{
			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
    if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
    {
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()!= odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
		else
		{
		    TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
    }
    else
    {
            cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
            exit(0); // plus tard on levera une exception
    }
  }
  else if (this->operateur=="==")
  {
	if( typeid(*og) == typeid(TypeInt) and typeid(*od) == typeid(TypeInt) )
  	{
  		TypeInt* ogi = dynamic_cast<TypeInt*> (og);
  		TypeInt* odi = dynamic_cast<TypeInt*> (od);

  		if (ogi->getValeur()== odi->getValeur())
		{
			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
  		else
  		{
	  		TypeBool* valeur = new TypeBool(false);
			return valeur;
	  	}
	  }
	  if( typeid(*og) == typeid(TypeFloat) and typeid(*od) == typeid(TypeFloat) )
  	  {
  		TypeFloat* ogi = dynamic_cast<TypeFloat*> (og);
  		TypeFloat* odi = dynamic_cast<TypeFloat*> (od);

  		if (ogi->getValeur()== odi->getValeur())
		{

			TypeBool* valeur = new TypeBool(true);
			return valeur;
		}
		else
		{
            TypeBool* valeur = new TypeBool(false);
			return valeur;
		}
  	  }
    else
    {
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
    }
  }
   else if (this->operateur=="non")
  {
	if( typeid(*od) == typeid(TypeBool) )
  	{
  		TypeBool* odi = dynamic_cast<TypeBool*> (od);
        TypeBool* val = new TypeBool (not odi->getValeur());
  		return val;
    }
	 else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que booléen." << endl;
	  	exit(0); // plus tard on levera une exception
  	}
  }




  return new TypeInt(0);

}

////////////////////////////////////////////////////////////////////////////////
void NoeudOperateurBinaire::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Operateur Binaire \"" << this->operateur.getChaine() << "\" applique a : " << endl;
  operandeGauche->afficher(indentation+1);  // on affiche fils gauche et fils droit
  operandeDroit->afficher(indentation+1);   // en augmentant l'indentation
}

string NoeudOperateurBinaire::getCode(int indent) {
	string boringBuff = "";

	if ( typeid(*operandeGauche) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(operandeGauche);
		boringBuff = boringBuff + temp->getChaine();
	} else {
		boringBuff = boringBuff + operandeGauche->getCode(indent);
	}

	boringBuff = boringBuff + operateur.getChaine();

	if ( typeid(*operandeDroit) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(operandeDroit);
		boringBuff = boringBuff + temp->getChaine();
	} else {
		boringBuff = boringBuff + operandeDroit->getCode(indent);
	}

	return boringBuff;
}



////////////////////////////////////////////////////////////////////////////////
// NoeudInstTq
////////////////////////////////////////////////////////////////////////////////

NoeudInstTq::NoeudInstTq(Noeud* expBool, Noeud* seqInst) {
	this->expBool = expBool;
	this->seqInst = dynamic_cast<NoeudSeqInst*> (seqInst);

}

////////////////////////////////////////////////////////////////////////////////

Multype* NoeudInstTq::getValeur() {
	Multype* valeur = NULL;
	Multype* og=expBool->getValeur();
	if( typeid(*og) == typeid(TypeBool) )
	{

		TypeBool* ogi = dynamic_cast<TypeBool*> (og);
		while (ogi->getValeur() )
		{
			valeur = seqInst->getValeur();
			og=expBool->getValeur();
			ogi = dynamic_cast<TypeBool*> (og);

		}
	}
	else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}

	return valeur;
}

////////////////////////////////////////////////////////////////////////////////


void NoeudInstTq::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Tantque";
	expBool->afficher();
	cout << "Faire";
	seqInst->afficher(indentation+1);
	cout << "FinTantque " << endl;

}

string NoeudInstTq::getCode(int indent) {

	string tq = "while ( ";

	if ( typeid(*expBool) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(expBool);
		tq = tq + temp->getChaine();
	} else {
		tq = tq + expBool->getCode(indent);
	}

	tq = tq + " ) {\n";
	indent++;

	tq = tq + seqInst->getCode(indent);

	indent--;

	for ( int i = 0 ; i < indent ; i++ )
		tq = tq + "\t";
	tq = tq + "}\n";

	return tq;
}
////////////////////////////////////////////////////////////////////////////////
// NoeudInstRepeter
////////////////////////////////////////////////////////////////////////////////

NoeudInstRepeter::NoeudInstRepeter(Noeud* expBool, Noeud* seqInst) {
	this->expBool = expBool;
	this->seqInst = dynamic_cast<NoeudSeqInst*> (seqInst);

}

void NoeudInstRepeter::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Répeter" << endl;
	seqInst->afficher(indentation+1);
	cout << "jusqu'à " << endl;
	expBool->afficher();
}

////////////////////////////////////////////////////////////////////////////////

Multype* NoeudInstRepeter::getValeur()
{
	Multype* valeur = NULL;
	Multype* og=expBool->getValeur();
	if( typeid(*og) == typeid(TypeBool) )
	{

		TypeBool* ogi = dynamic_cast<TypeBool*> (og);
		do
		{
			valeur = seqInst->getValeur();
			og=expBool->getValeur();
			ogi = dynamic_cast<TypeBool*> (og);

		}while (ogi->getValeur() );
	}
	else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}

	return valeur;
}

string NoeudInstRepeter::getCode(int indent) {
	string rep = "do {\n";

	indent++;
	rep = rep + seqInst->getCode(indent);
	indent--;

	rep = rep + "\n";
	for ( int i = 0 ; i < indent ; i++ )
		rep = rep + "\t";
	rep = rep + "} while ( ";

	if ( typeid(*expBool) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(expBool);
		rep = rep + temp->getChaine();
	} else {
		rep = rep + expBool->getCode(indent);
	}
	rep = rep + " );\n";

	return rep;
}

////////////////////////////////////////////////////////////////////////////////

void NoeudInstPour::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Pour" << endl;
	affectation->afficher(indentation +1);
	expBool->afficher(indentation+1);
	affectationPour->afficher(indentation+1);
	cout << "faire" << endl;
	seqInst->afficher(indentation+1);
	cout << "finPour" << endl;
	expBool->afficher();
}

////////////////////////////////////////////////////////////////////////////////


NoeudInstPour::NoeudInstPour(Noeud* expBool, Noeud* seqInst, Noeud* aff, Noeud* aff2)
{
	this->expBool = expBool;
	this->seqInst = dynamic_cast<NoeudSeqInst*> (seqInst);
	this->affectation = aff;
	this->affectationPour = aff2;
}

////////////////////////////////////////////////////////////////////////////////

Multype* NoeudInstPour::getValeur()
{
	Multype* valeur = NULL;
	Multype* og=affectation->getValeur();

		TypeBool* ogi = dynamic_cast<TypeBool*> (og);
		do
		{
			valeur = seqInst->getValeur();
			og=expBool->getValeur();
			ogi = dynamic_cast<TypeBool*> (og);
            valeur = affectationPour->getValeur();
		}while (ogi->getValeur() );

	return valeur;
}

string NoeudInstPour::getCode(int indent) {
	string pour = "for ( ";
	pour = pour + affectation->getCode(indent) + " ; ";

	if ( typeid(*expBool) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(expBool);
		pour = pour + temp->getChaine();
	} else {
		pour = pour + expBool->getCode(indent);
	}

	pour = pour + " ; " + affectationPour->getCode(indent) + " ) {\n";

	indent++;
	pour = pour + seqInst->getCode(indent);
	indent--;

	for ( int i = 0 ; i < indent ; i++ )
		pour = pour + "\t";
	pour = pour + "}\n";

	return pour;
}

////////////////////////////////////////////////////////////////////////////////

NoeudInstLire::NoeudInstLire(Noeud* var)
{
	this->variable = var;
}

Multype* NoeudInstLire::getValeur()
{
	SymboleValue* s = dynamic_cast<SymboleValue*> (variable);
	Multype* val=variable->getValeur();

	if( typeid(*val) == typeid(TypeInt) )
	{

		int a;
		cout << "Entrez la variable entière : " << endl;
		cin >> a;
		cin.ignore(256, '\n');
		s->setValeur(a);
		return s->getValeur();
	}
	else
	{
		string a;
		cout << "Entrez la variable : " << endl;
		getline(cin, a);
		s->setValeur(a);
		return s->getValeur();
	}
	return new TypeInt(0);
}

void NoeudInstLire::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Lire" << endl;
	cout << "Lire :" << endl;
	variable->afficher(indentation +1);
}

string NoeudInstLire::getCode(int indent) {
	SymboleValue* s = dynamic_cast<SymboleValue*> (variable);

	string lire;

	lire = "cin >> " + s->getChaine() + ";\n" ;

	for ( int i = 0 ; i < indent ; i++ )
		lire = lire + "\t";
	lire = lire + "cin.ignore(256, '\\n');";

	return lire;
}

////////////////////////////////////////////////////////////////////////////////////////

NoeudInstEcrire::NoeudInstEcrire(Noeud* var)
{
	this->variable = var;
}


Multype* NoeudInstEcrire::getValeur()
{
	Multype* val=variable->getValeur();

	if( typeid(*val) == typeid(TypeInt) )
	{
		TypeInt* i = dynamic_cast<TypeInt*> (val);
		cout << i->getValeur() << endl;
		return val;
	}
	else if( typeid(*val) == typeid(TypeString) )
	{
		TypeString* i = dynamic_cast<TypeString*> (val);
		cout << i->getValeur()<< endl;
		return val;
	}
	else if( typeid(*val) == typeid(TypeFloat) )
	{
		TypeFloat* i = dynamic_cast<TypeFloat*> (val);
		cout << i->getValeur()<< endl;
		return val;
	}
	else
	{
		//cas d'une expression
	}
	return new TypeInt(0);
}

string NoeudInstEcrire::getCode(int indent) {
	SymboleValue* s = dynamic_cast<SymboleValue*> (variable);

	string ecrire;

	ecrire = "cout << " + s->getChaine() + ";\n" ;

	return ecrire;
}

void NoeudInstEcrire::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Ecrire" << endl;
	cout << "Ecrire :" << endl;
	variable->afficher(indentation +1);
}

////////////////////////////////////////////////////////////////////////////////////////

NoeudInstSi::NoeudInstSi(Noeud* exp, Noeud* inst1, Noeud*  inst2)
{
	this->expBool = exp;
	this->instGauche = dynamic_cast<NoeudSeqInst*> (inst1);
	this->instDroit = inst2;
}


Multype* NoeudInstSi::getValeur()
{
	Multype* valeur = NULL;
	Multype* exp=expBool->getValeur();
	if( typeid(*exp) == typeid(TypeBool) )
	{

		TypeBool* expInt = dynamic_cast<TypeBool*> (exp);
		if (expInt->getValeur() )
		{
			return instGauche->getValeur();
		}
		else
		{
			if(typeid(*instDroit) == typeid(NoeudInstSi) )
			{
				NoeudInstSi* noeud = dynamic_cast<NoeudInstSi*> (instDroit);
				return noeud->getValeur();
			}
			else if(instDroit != NULL)
			{
				NoeudSeqInst* noeud = dynamic_cast<NoeudSeqInst*> (instDroit);
				return  noeud->getValeur();
			}
			return new TypeInt(0);
		}
	}
	else
	{
	  	cout << "Erreur pendant l'interpretation : condition expression booléenne avec un type autre que entier" << endl;
	  	exit(0); // plus tard on levera une exception
  	}

	return valeur;
}

void NoeudInstSi::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Si"<< endl;
	expBool->afficher(indentation++);
	cout << "Alors" << endl;
	instGauche->afficher(indentation++);
	if(instDroit != NULL)
	{
		cout << "Sinon" << endl;
		if(typeid(*instDroit) == typeid(NoeudInstSi) )
		{
			NoeudInstSi* noeud = dynamic_cast<NoeudInstSi*> (instDroit);
			noeud->afficher();
		}
		else
		{
			NoeudSeqInst* noeud = dynamic_cast<NoeudSeqInst*> (instDroit);
			noeud->afficher();
		}
	}
	cout << "Finsi"<< endl;

}

string NoeudInstSi::getCode(int indent) {
	string si = "if ( ";

	if ( typeid(*expBool) == typeid(SymboleValue) ) {
		SymboleValue* temp = dynamic_cast<SymboleValue*>(expBool);
		si = si + temp->getChaine();
	} else {
		si = si + expBool->getCode(indent);
	}

	si = si + " ) {\n";

	indent++;
	si = si + instGauche->getCode(indent);
	indent--;

	if ( instDroit != NULL ) {
		for ( int i = 0 ; i < indent ; i++ )
				si = si + "\t";
		si = si + "} else ";
		if ( typeid(*instDroit) == typeid(NoeudInstSi()) ) {
			si = si + instDroit->getCode(indent);
		} else {
			si = si + "{\n";
			indent++;
			for ( int i = 0 ; i < indent ; i++ )
				si = si + "\t";
			si = si + instDroit->getCode(indent);
			indent--;
		}
	}

	for ( int i = 0 ; i < indent ; i++ )
			si = si + "\t";
	si = si + "}\n";

	return si;
}

////////////////////////////////////////////////////////////////////////////////////////

NoeudInstAppelFonction::NoeudInstAppelFonction( NoeudSeqInst* f,  vector<Noeud*> p,  vector<SymboleValue*> & _param, string nom)
{
	fonction = f;
	pile = p;
	param = _param;
	this->nom = nom;
}


Multype* NoeudInstAppelFonction::getValeur()
{
    if(pile.size() != param.size())
    {
        cout << "Nombre de paramètre de la fonction incorrect" << endl;
        exit(0);
    }
    int i = 0;
    while(i < pile.size())
    {
        Multype* valeur = pile[i]->getValeur();
        if(typeid(*valeur) == typeid(TypeInt))
        {
            TypeInt* val = dynamic_cast<TypeInt*> (valeur);
            param[i]->setValeur(val->getValeur());
        }
        else if(typeid(*valeur) == typeid(TypeString))
        {
            TypeString* val = dynamic_cast<TypeString*> (valeur);
            param[i]->setValeur(val->getValeur());
        }
        i++;
    }


    Multype* m = fonction->getValeur();
    fonction->afficher(4);
    if(typeid(*m) == typeid(TypeInt))
        {
            TypeInt* val = dynamic_cast<TypeInt*> (m);
        }
        else if(typeid(*m) == typeid(TypeString))
        {
            TypeString* val = dynamic_cast<TypeString*> (m);
        }

    return m;

}

void NoeudInstAppelFonction::afficher(unsigned short indentation)
{
	Noeud::afficher(indentation);
	cout << "Noeud - Appel Fonction"<< endl;
	//LecteurFonction* f = dynamic_cast<LecteurFonction*> (fonction);
    fonction->afficher(indentation+1);
}

string NoeudInstAppelFonction::getCode(int indent) {
    string s =  nom + " ( " ;
    for (int i = 0; i < pile.size(); i++)
    {   if( typeid(*pile[i]) == typeid(SymboleValue) )
        {
            SymboleValue* symb = dynamic_cast<SymboleValue*> (pile[i]);
            s += symb->getChaine();
            if(i != (pile.size() -1) )
                s += " , ";
        }
        else
        {
            s += pile[i]->getCode(indent);
            if(i != (pile.size() -1) )
                s += " , ";
        }
    }
    s += " ); \n";
    return s;
}
